[Chapter Thirteen][Previous]
[Next] [Art of
Assembly][Randall Hyde]
Art of Assembly: Chapter Thirteen
- 13.2.6 - INT 14h - Serial I/O
- 13.2.6.1 - AH=0: Serial Port Initialization
- 13.2.6.2 - AH=1: Transmit a Character
to the Serial Port
- 13.2.6.3 - AH=2: Receive a Character from
the Serial Port
- 13.2.6.4 - AH=3: Serial Port Status
- 13.2.7 - INT 15h - Miscellaneous Services
- 13.2.8 - INT 16h - Keyboard Services
- 13.2.8.1 - AH=0: Read a Key From the Keyboard
- 13.2.8.2 - AH=1: See if a Key is Available
at the Keyboard
- 13.2.8.3 - AH=2: Return Keyboard Shift
Key Status
- 13.2.9 - INT 17h - Printer Services
- 13.2.9.1 - AH=0: Print a Character
- 13.2.9.2 - AH=1: Initialize Printer
- 13.2.9.3 - AH=2: Return Printer Status
- 13.2.10 - INT 18h - Run BASIC
- 13.2.11 - INT 19h - Reboot Computer
- 13.2.12 - INT 1Ah - Real Time Clock
- 13.2.12.1 - AH=0: Read the Real Time
Clock
- 13.2.12.2 - AH=1: Setting the Real Time
Clock
13.2.6 INT 14h - Serial I/O
Instruction: int 14h
BIOS Operation: Access the serial communications port
Parameters: ax, dx
The IBM BIOS supports up to four different serial communications ports (the
hardware supports up to eight). In general, most PCs have one or two serial
ports (COM1: and COM2:) installed. Int 14h
supports four subfunctions-
initialize, transmit a character, receive a character, and status. For all
four services, the serial port number (a value in the range 0..3) is in
the dx
register (0=COM1:, 1=COM2:, etc.). Int 14h
expects
and returns other data in the al
or ax
register.
13.2.6.1 AH=0: Serial Port Initialization
Subfunction zero initializes a serial port. This call lets you set the
baud rate, select parity modes, select the number of stop bits, and the
number of bits transmitted over the serial line. These parameters are all
specified by the value in the al
register using the following
bit encodings:
Bits Function
5..7 Select baud rate
000- 110 baud
001- 150
010- 300
011- 600
100- 1200
101- 2400
110- 4800
111- 9600
3..4 Select parity
00- No parity
01- Odd parity
10- No parity
11- Even parity
2 Stop bits
0-One stop bit
1-Two stop bits
0..1 Character Size
10- 7 bits
11- 8 bits
Although the standard PC serial port hardware supports 19,200 baud, some
BIOSes may not support this speed.
Example: Initialize COM1: to 2400 baud, no parity, eight bit data, and two
stop bits-
mov ah, 0 ;Initialize opcode
mov al, 10100111b ;Parameter data.
mov dx, 0 ;COM1: port.
int 14h
After the call to the initialization code, the serial port status is returned
in ax
(see Serial Port Status, ah
=3, below).
13.2.6.2 AH=1: Transmit a Character to the Serial Port
This function transmits the character in the al
register
through the serial port specified in the dx
register. On return,
if ah
contains zero, then the character was transmitted properly.
If bit 7 of ah
contains one, upon return, then some sort of
error occurred. The remaining seven bits contain all the error statuses
returned by the GetStatus
call except time out error (which
is returned in bit seven). If an error is reported, you should use subfunction
three to get the actual error values from the serial port hardware.
Example: Transmit a character through the COM1: port
mov dx, 0 ;Select COM1:
mov al, 'a' ;Character to transmit
mov ah, 1 ;Transmit opcode
int 14h
test ah, 80h ;Check for error
jnz SerialError
This function will wait until the serial port finishes transmitting the
last character (if any) and then it will store the character into the transmit
register.
13.2.6.3 AH=2: Receive a Character from the Serial Port
Subfunction two is used to read a character from the serial port. On
entry, dx
contains the serial port number. On exit, al
contains the character read from the serial port and bit seven of
ah
contains the error status. When this routine is called,
it does not return to the caller until a character is received at the serial
port.
Example: Reading a character from the COM1: port
mov dx, 0 ;Select COM1:
mov ah, 2 ;Receive opcode
int 14h
test ah, 80h ;Check for error
jnz SerialError
<Received character is now in AL>
13.2.6.4 AH=3: Serial Port Status
This call returns status information about the serial port including
whether or not an error has occurred, if a character has been received in
the receive buffer, if the transmit buffer is empty, and other pieces of
useful information. On entry into this routine, the dx
register
contains the serial port number. On exit, the ax
register contains
the following values:
AX: Bit Meaning
15 Time out error
14 Transmitter shift register empty
13 Transmitter holding register empty
12 Break detection error
11 Framing error
10 Parity error
9 Overrun error
8 Data available
7 Receive line signal detect
6 Ring indicator
5 Data set ready (DSR)
4 Clear to send (CTS)
3 Delta receive line signal detect
2 Trailing edge ring detector
1 Delta data set ready
0 Delta clear to send
There are a couple of useful bits, not pertaining to errors, returned in
this status information. If the data available bit is set (bit #8), then
the serial port has received data and you should read it from the serial
port. The Transmitter holding register empty bit (bit #13) tells you if
the transmit operation will be delayed while waiting for the current character
to be transmitted or if the next character will be immediately transmitted.
By testing these two bits, you can perform other operations while waiting
for the transmit register to become available or for the receive register
to contain a character.
If you're interested in serial communications, you should obtain a copy
of Joe Campbell's C Programmer's Guide to Serial Communications. Although
written specifically for C programmers, this book contains a lot of information
useful to programmers working in any programming language. See the bibliography
for more details.
13.2.7 INT 15h - Miscellaneous Services
Originally, int 15h
provided cassette tape read and write
services[1]. Almost immediately, everyone realized
that cassettes were history, so IBM began using int 15h
for
many other services. Today, int 15h
is used for a wide variety
of function including accessing expanded memory, reading the joystick/game
adapter card, and many, many other operations. Except for the joystick calls,
most of these services are beyond the scope of this text. Check on the bibliography
if you interested in obtaining information on this BIOS call.
13.2.8 INT 16h - Keyboard Services
Instruction: int 16h
BIOS Operation: Read a key, test for a key, or get keyboard status
Parameters: al
The IBM PC BIOS provides several function calls dealing with the keyboard.
As with many of the PC BIOS routines, the number of functions has increased
over the years. This section describes the three calls that were available
on the original IBM PC.
13.2.8.1 AH=0: Read a Key From the Keyboard
If int 16h
is called with ah
equal to zero,
the BIOS will not return control to the caller until a key is available
in the system type ahead buffer. On return, al
contains the
ASCII code for the key read from the buffer and ah
contains
the keyboard scan code. Keyboard scan codes are described in the appendices.
Certain keys on the PC's keyboard do not have any corresponding ASCII codes.
The function keys, Home, PgUp, End, PgDn, the arrow keys, and the Alt keys
are all good examples. When such a key is pressed, int 16h
returns
a zero in al
and the keyboard scan code in ah
.
Therefore, whenever an ASCII code of zero is returned, you must check the
ah
register to determine which key was pressed.
Note that reading a key from the keyboard using the BIOS int 16h
call
does not echo the key pressed to the display. You have to call putc
or use int 10h
to print the character once you've read it if
you want it echoed to the screen.
Example: Read a sequence of keystrokes from the keyboard until Enter is
pressed.
ReadLoop: mov ah, 0 ;Read Key opcode
int 16h
cmp al, 0 ;Special function?
jz ReadLoop ;If so, don't echo this keystroke
putc
cmp al, 0dh ;Carriage return (ENTER)?
jne ReadLoop
13.2.8.2 AH=1: See if a Key is Available at the Keyboard
This particular int 16h
subfunction allows you to check
to see if a key is available in the system type ahead buffer. Even if a
key is not available, control is returned (right away!) to the caller. With
this call you can occasionally poll the keyboard to see if a key is available
and continue processing if a key hasn't been pressed (as opposed to freezing
up the computer until a key is pressed).
There are no input parameters to this function. On return, the zero flag
will be clear if a key is available, set if there aren't any keys in the
type ahead buffer. If a key is available, then ax
will contain
the scan and ASCII codes for that key. However, this function will not remove
that keystroke from the typeahead buffer. Subfunction #0 must be used to
remove characters. The following example demonstrates how to build a random
number generator using the test keyboard function:
Example: Generating a random number while waiting for a keystroke
; First, clear any characters out of the type ahead buffer
ClrBuffer: mov ah, 1 ;Is a key available?
int 16h
jz BufferIsClr ;If not, Discontinue flushing
mov ah, 0 ;Flush this character from the
int 16h ; buffer and try again.
jmp ClrBuffer
BufferIsClr: mov cx, 0 ;Initialize "random" number.
GenRandom: inc cx
mov ah, 1 ;See if a key is available yet.
int 16h
jz GenRandom
xor cl, ch ;Randomize even more.
mov ah, 0 ;Read character from buffer
int 16h
; Random number is now in CL, key pressed by user is in AX
While waiting for a key, this routine is constantly incrementing the cx
register. Since human beings cannot respond rapidly (at least in
terms of microseconds) the cl
register will overflow many times,
even for the fastest typist. As a result, cl
will contain a
random value since the user will not be able to control (to better than
about 2ms) when a key is pressed.
13.2.8.3 AH=2: Return Keyboard Shift Key Status
This function returns the state of various keys on the PC keyboard in
the al
register. The values returned are as follows:
Bit Meaning
7 Insert state (toggle by pressing INS key)
6 Caps lock (1=capslock on)
5 Num lock (1=numlock on)
4 Scroll lock (1=scroll lock on)
3 Alt (1=Alt key currently down)
2 Ctrl (1=Ctrl key currently down)
1 Left shift (1=left shift key down)
0 Right shift (1=right shift key down)
Due to a bug in the BIOS code, these bits only reflect the current status
of these keys, they do not necessarily reflect the status of these keys
when the next key to be read from the system type ahead buffer was depressed.
In order to ensure that these status bits correspond to the state of these
keys when a scan code is read from the type ahead buffer, you've got to
flush the buffer, wait until a key is pressed, and then immediately check
the keyboard status.
13.2.9 INT 17h - Printer Services
Instruction: int 17h
BIOS Operation: Print data and test the printer status
Parameters: ax, dx
Int 17h
controls the parallel printer interfaces on the IBM
PC in much the same way the int 14h
controls the serial ports.
Since programming a parallel port is considerably easier than controlling
a serial port, using the int 17h
routine is somewhat easier
than using the int 14h
routines.
Int 17h
provides three subfunctions, specified by the value
in the ah
register. These subfunctions are:
0-Print the character in the AL register.
1-Initialize the printer.
2-Return the printer status.
Each of these functions is described in the following sections.
Like the serial port services, the printer port services allow you to specify
which of the three printers installed in the system you wish to use (LPT1:,
LPT2:, or LPT3:). The value in the dx
register (0..2) specifies
which printer port is to be used.
One final note- under DOS it's possible to redirect all printer output to
a serial port. This is quite useful if you're using a serial printer. The
BIOS printer services only talk to parallel printer adapters. If you need
to send data to a serial printer using BIOS, you'll have to use int
14h
to transmit the data through a serial port.
13.2.9.1 AH=0: Print a Character
If ah
is zero when you call int 17h
, then
the BIOS will print the character in the al
register. Exactly
how the character code in the al
register is treated is entirely
up to the printer device you're using. Most printers, however, respect the
printable ASCII character set and a few control characters as well. Many
printers will also print all the symbols in the IBM/ASCII character set
(including European, line drawing, and other special symbols). Most printers
treat control characters (especially ESC sequences) in completely different
manners. Therefore, if you intend to print something other than standard
ASCII characters, be forewarned that your software may not work on printers
other than the brand you're developing your software on.
Upon return from the int 17h
subfunction zero routine, the
ah
register contains the current status. The values actually
returned are described in the section on subfunction number two.
13.2.9.2 AH=1: Initialize Printer
Executing this call sends an electrical impulse to the printer telling
it to initialize itself. On return, the ah
register contains
the printer status as per function number two.
13.2.9.3 AH=2: Return Printer Status
This function call checks the printer status and returns it in the ah
register. The values returned are:
AH: Bit Meaning
7 1=Printer busy, 0=printer not busy
6 1=Acknowledge from printer
5 1=Out of paper signal
4 1=Printer selected
3 1=I/O error
2 Not used
1 Not used
0 Time out error
Acknowledge from printer is, essentially, a redundant signal (since printer
busy/not busy gives you the same information). As long as the printer is
busy, it will not accept additional data. Therefore, calling the print character
function (ah
=0) will result in a delay.
The out of paper signal is asserted whenever the printer detects that it
is out of paper. This signal is not implemented on many printer adapters.
On such adapters it is always programmed to a logic zero (even if the printer
is out of paper). Therefore, seeing a zero in this bit position doesn't
always guarantee that there is paper in the machine. Seeing a one here,
however, definitely means that your printer is out of paper.
The printer selected bit contains a one as long as the printer is on-line.
If the user takes the printer off-line, then this bit will be cleared.
The I/O error bit contains a one if some general I/O error has occurred.
The time out error bit contains a one if the BIOS routine waited for an
extended period of time for the printer to become "not busy" yet
the printer remained busy.
Note that certain peripheral devices (other than printers) also interface
to the parallel port, often in addition to a parallel printer. Some of these
devices use the error/status signal lines to return data to the PC. The
software controlling such devices often takes over the int 17h
routine
(via a technique we'll talk about later on) and always returns a "no
error" status or "time out error" status if an error occurs
on the printing device. Therefore, you should take care not to depend too
heavily on these signals changing when you make the int 17h
BIOS
calls.
13.2.10 INT 18h - Run BASIC
Instruction: int 18h
BIOS Operation: Activate ROM BASIC
Parameters: None
Executing int 18h
activates the ROM BASIC interpreter in an
IBM PC. However, you shouldn't use this mechanism to run BASIC since many
PC compatibles do not have BASIC in ROM and the result of executing int
18h
is undefined.
13.2.11 INT 19h - Reboot Computer
Instruction: int 19h
BIOS Operation: Restart the system
Parameters: None
Executing this interrupt has the same effect as pressing control-alt-del
on the keyboard. For obvious reasons, this interrupt service should be handled
carefully!
13.2.12 INT 1Ah - Real Time Clock
Instruction: int 1ah
BIOS Operation: Real time clock services
Parameters: ax, cx, dx
There are two services provided by this BIOS routine- read the clock and
set the clock. The PC's real time clock maintains a counter that counts
the number of 1/18ths of a second that have transpired since midnight. When
you read the clock, you get the number of "ticks" which have occurred
since then. When you set the clock, you specify the number of "ticks"
which have occurred since midnight. As usual, the particular service is
selected via the value in the ah
register.
13.2.12.1 AH=0: Read the Real Time Clock
If ah
= 0, then int 1ah
returns a 33-bit value
in al:cx:dx
as follows:
Reg Value Returned
dx L.O. word of clock count
cx H.O. word of clock count
al Zero if timer has not run for more than 24 hours
Non-zero otherwise.
The 32-bit value in cx:dx
represents the number of 55 millisecond
periods which have elapsed since midnight.
13.2.12.2 AH=1: Setting the Real Time Clock
This call allows you to set the current system time value. cx:dx
contains the current count (in 55ms increments) since last midnight.
Cx
contains the H.O. word, dx
contains the L.O.
word.
[1] For those who do not remember that far
back, before there were hard disks people used to use only floppy disks.
And before there were floppy disks, people used to use cassette tapes to
store programs and data. The original IBM PC was introduced in late 1981
with a cassette port. By early 1982, no one was using cassette tape for
data storage.
- 13.2.6 - INT 14h - Serial I/O
- 13.2.6.1 - AH=0: Serial Port Initialization
- 13.2.6.2 - AH=1: Transmit a Character
to the Serial Port
- 13.2.6.3 - AH=2: Receive a Character from
the Serial Port
- 13.2.6.4 - AH=3: Serial Port Status
- 13.2.7 - INT 15h - Miscellaneous Services
- 13.2.8 - INT 16h - Keyboard Services
- 13.2.8.1 - AH=0: Read a Key From the Keyboard
- 13.2.8.2 - AH=1: See if a Key is Available
at the Keyboard
- 13.2.8.3 - AH=2: Return Keyboard Shift
Key Status
- 13.2.9 - INT 17h - Printer Services
- 13.2.9.1 - AH=0: Print a Character
- 13.2.9.2 - AH=1: Initialize Printer
- 13.2.9.3 - AH=2: Return Printer Status
- 13.2.10 - INT 18h - Run BASIC
- 13.2.11 - INT 19h - Reboot Computer
- 13.2.12 - INT 1Ah - Real Time Clock
- 13.2.12.1 - AH=0: Read the Real Time
Clock
- 13.2.12.2 - AH=1: Setting the Real Time
Clock
Art of Assembly: Chapter Thirteen - 28 SEP 1996
[Chapter Thirteen][Previous]
[Next] [Art of
Assembly][Randall Hyde]